#ifndef __mesh__h__included__
#define __mesh__h__included__

#include "Object.h"

#include "neiderra/math/Vectors.h"

#include "neiderra/core/Defs.h"
#include "Texture.h"
#include "Image.h"

#include <string>
#include <vector>

using neiderra::rendering::Image;
using neiderra::rendering::Texture;
using neiderra::math::vec3;
using std::vector;
using std::string;

namespace neiderra {
	namespace rendering {

#ifdef _MSC_VER
#pragma pack( push, 1 )
#endif


//#ifdef _MSC_VER
//#pragma pack(1)
//#endif
//		struct face {
//			unsigned short v1;
//			unsigned short v2;
//			unsigned short v3;
////			unsigned short flags;
//		} PACKED_STRUCTURE ;
//
//		struct mapstruct {
//			float u;
//			float v;
//		} PACKED_STRUCTURE ;
//
//#ifdef _MSC_VER
//#pragma pack(1)
//#endif
//		struct vertex {
//			float x;
//			float y;
//			float z;
//		} PACKED_STRUCTURE;

		struct face {
			unsigned int v1;
			unsigned int v2;
			unsigned int v3;
		};

		struct mapstruct {
			float u;
            float v;
		};

		struct vertex {
			float x;
			float y;
			float z;
		};

		//! 3d-mesh
		class Mesh: public RenderingObject{
		public:
			Mesh();
			Mesh(Core* core);
			virtual ~Mesh();

			void setVertices(vertex* vp, unsigned n);
			void setFaces(face* fp, unsigned n);
			void setMapList(mapstruct* m, unsigned n) { _maplist = m; _mapnum = n; }
			void setNormals(vec3* normals, unsigned n) {_normals = normals; _normnum = n;}
			void setTexture(Texture* texture);
			void setMaxSize(unsigned);
			void setScaleFactor(float f) {_scaleFactor = f; }
			
			void getMaxDims(vec3&);
			void setMaxDims(vec3& v) {_maxDims = v;}

			vertex* getVertices(){return vertices_;}
			face* getFaces(){return faces_;}
			mapstruct* getMapList() {return _maplist;}
			unsigned getVertexNum(){ return vertnum_; }
			unsigned getFaceNum(){ return facenum_; }
			unsigned getMapsNum(){ return _mapnum; }
			Texture* getTexture() { return _texture; }
			float getScaleFactor() {return _scaleFactor; }
			//int getTextureName() { return _textureName; }
			vec3* getNormals() { return _normals; }
			unsigned getNormalsNum() { return _normnum; }
			float* getLocalTransform() { return _localTransform; }
			void setLocalTransform(float* tr) { _localTransform = tr; }
			unsigned getMaxSize();

			void scaleToMaxSize(); 

		protected:
			face* faces_;
			mapstruct* _maplist;
			vertex* vertices_;
			unsigned facenum_;
			unsigned vertnum_;
			unsigned _mapnum;
			//Image* _texture;
			//int _textureName;
			Texture* _texture;
			vec3* _normals;
			unsigned int _normnum;
			float *_localTransform;
			vec3 _maxDims;
			float _scaleFactor;

			unsigned _maxSize;

		public:
			string _name;
		};

		typedef std::vector<Mesh*> Meshes;

		class MeshObjects{
		public:
			Meshes meshes;
			float scaleFactor;

			MeshObjects() { scaleFactor = 1; }

			void setScaleFactor(float f) { scaleFactor=f; }

			void add(Mesh* m)
			{
				meshes.push_back(m);
			}

			Mesh* get(const string& name)
			{
				Meshes::iterator i = meshes.begin();
				for(;i!=meshes.end();i++)
				{
					Mesh* m = *i;
					if(m->_name == name){
						return m;
					}
				}
				return 0;
			}

			void clear()
			{
				meshes.clear();
			}
			Mesh* get(unsigned i)
			{
				if(i>meshes.size()) return 0;
				return meshes[i];
			}
			unsigned size()
			{
				return meshes.size();
			}
			virtual ~MeshObjects()
			{
				meshes.clear();
			}
		};

#ifdef _MSC_VER
#pragma pack( pop, 1 )
#endif

	}
}


#endif
